"use strict";

function Format() {}

/**
 * Format date as Month Day, Year (March 15, 1973)
 * @param {Date} d Date to be formatted
 * @return {String}
 * @static
 */
Format.date = function(d)
{
	"use strict";

	return Enum.month[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear();
};

/**
 * Replace placeholders with arbitrary arguments
 * @param {String} text
 * @return {String}
 */
Format.string = function(text)
{
	"use strict";

	for (var i = 0; i < arguments.length - 1; i++)
	{
		text = text.replace('{' + i + '}', arguments[i + 1]);
	}
	return text;
};

/**
 * Convert text to date object
 * @param {String} text
 * @return {Date}
 */
Format.parseDate = function(text)
{
	"use strict";

	// e.g. '2012-06-17 17:34:33'
	// new Date(year, month, day, hours, minutes, seconds, milliseconds);
	var parts = text.split(' ');
	var date = parts[0].split('-');
	var time = parts[1].split(':');
	return new Date(date[0], date[1] - 1, date[2], time[0], time[1], time[2]);
};

/**
 * Remove non-numeric characters from string
 * @param {String} text
 * @return {Number}
 */
Format.parseNumber = function(text)
{
	text = (text ? text : '').replace(/[^\d\.]/g, '');
	return (Format.isEmpty(text)) ? NaN : parseFloat(text);
};

/**
 * Shuffle an array
 * @return {Array}
 * @see http://sroucheray.org/blog/2009/11/array-sort-should-not-be-used-to-shuffle-an-array/
 * @static
 */
Format.shuffle = function(a)
{
	"use strict";

	var i = a.length, j, temp;
	if (i == 0) return null;
	while (--i)
	{
		j = Math.floor(Math.random() * (i + 1));
		temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
	return a;
};

/**
 * Stylize punctuation
 * @param {String} text
 * @return {String}
 * @static
 */
Format.text = function(text)
{
	"use strict";

	return (Format.isEmpty(text)) ? null : text
		.replace(/(\w)'/g, '$1&rsquo;')
		.replace(/\b'(\w)/g, '&lsquo;$1')
		.replace(/(\w)("|&quot;)/g, '$1&rdquo;')
		.replace(/("|&quot;)(\w)/g, '&ldquo;$2')
		.replace(/(<a [^>]+>)([^<]+)<\/a>/gi, function(match, tag, url)
		{
			// restore links injected by Flickr
			return tag.replace(/(&ldquo;|&rdquo;)/g, '"') + url + '</a>';
		});
};

/**
 * @param {String} text
 * @return {String}
 * @static
 */
Format.story = function(text)
{
	"use strict";

	if (!Format.isEmpty(text))
	{
		var re = Enum.pattern.haiku;

		if (re.test(text))
		{
			re.lastIndex = 0;

			var match = re.exec(text);

			text = '<p class="haiku">'
				+ match[1] + '<br/>'
				+ match[2] + '<br/>'
				+ match[3] + '</p>'
				+ Format.paragraph(text.replace(match[0], ''));

			re.lastIndex = 0;
		}
		else
		{
			text = Format.paragraph(text);
		}
	}
	return text;
};

/**
 * Convert new lines to HTML paragraphs and normalize links
 * @param {String} text Plain text
 * @return {String} HTML formatted text
 * @see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/replace
 */
Format.paragraph = function(text)
{
	"use strict";

	if (!Format.isEmpty(text))
	{
		text = '<p class="first">' + Format.text(text) + '</p>';

		return text
			.replace(Enum.pattern.link, function(match, url)
			{
				return '<a href="' + url + '">' + url.split('/')[2] + '/&hellip;</a>';
			})
			.replace(Enum.pattern.newLine, '</p><p>')
			.replace(Enum.pattern.footnotes, function(match)
			{
				return '<div class="footnotes">' + match
					.replace(/[¹]\s*/g, '<sup>1.</sup>')
					.replace(/[²]\s*/g, '<sup>2.</sup>')
					.replace(/[³]\s*/g, '<sup>3.</sup>') + '</div>';
			})
			.replace(Enum.pattern.superscript, '<sup>$1</sup>')
	}
	return '';
};

/**
 * Check if text is any kind of empty
 * @param {String} text
 * @return {Boolean}
 * @static
 */
Format.isEmpty = function(text)
{
	"use strict";

	return text === null || text === undefined || text === "";
};
